function Wizard(wizardContainer, btnPrev, btnNext) {
	this._steps = new Array();
	this._activeStep = null;
	this._activeStepIx = -1;
	this._container = wizardContainer;
	this._header = null;
	this._btnPrev = null;
	this._btnNext = null;
	this.onFinish = function() { }
	this.onChangeStep = function(stepIx) { }
	// event handlers
	this.events = {
		anchor_onClick: this.anchor_onClick.bindAsEventListener(this),
		btnNext_onClick: this.btnNext_onClick.bindAsEventListener(this),
		btnPrev_onClick: this.btnPrev_onClick.bindAsEventListener(this)
	};
		
	// btns
	if(btnPrev) {
		this._btnPrev = btnPrev;
		Event.observe(this._btnPrev, "click", this.events.btnPrev_onClick);
	}
	if(btnNext) {
		this._btnNext = btnNext;
		Event.observe(this._btnNext, "click", this.events.btnNext_onClick);
	}
}

Wizard.prototype.getSteps = function() {
	return this._steps.clone(false);
}

Wizard.prototype.addStep = function(stepTitle, stepControl, validation) {
	if(!validation) validation = null;
	var step = {title:stepTitle, control:stepControl, index:this._steps.length, validation:validation};
	this._steps.push(step);
}

Wizard.prototype.getStep = function(stepIx) {
	var step = this._steps[stepIx];
	if(step == undefined) step = null;
	return step;
}

Wizard.prototype.getActiveStep = function() {
	return this._activeStep;
}

Wizard.prototype.buildHeader = function() {
	if(this._header == null) {
		var firstChild = this._container.childNodes[0];
		if(!firstChild) firstChild = null;
		var div = document.createElement("div");
		div.className = "wizardHeader";
		this._container.insertBefore(div, firstChild);
		this._header = div;
	} else {
		this.clearContainerContents(this._header);
	}
	var ul = document.createElement("ul");
	this._header.appendChild(ul);
	for(var i=0; i<this._steps.length; i++) {
		var step = this._steps[i];
		var li = document.createElement("li");
		if(this._activeStep == step) {
			var span = document.createElement("span");
			span.appendChild(document.createTextNode( step.title ));
			li.appendChild(span);
			li.className = "active";
		} else {
			var a = document.createElement("a");
			a.stepIx = i;
			a.href = "javascript:void(0);";
			a.onclick = this.events.anchor_onClick;
			var span = document.createElement("span");
			span.appendChild(document.createTextNode( step.title ));
			a.appendChild(span);
			li.appendChild(a);
		}
		ul.appendChild(li);
	}
	

}

Wizard.prototype.setActiveStep = function(stepIx) {
	if(stepIx < 0) return;
	var finished = false;
	if(this._activeStep != null && this._activeStep.validation && !this._activeStep.validation.validate()) return;
	var step = this.getStep(stepIx);
	if(stepIx >= this._steps.length) {
		// finish
		finished = true;
	} else if(this._activeStep != step) {
		if(this._activeStep != null) Element.removeClassName(this._activeStep.control, "on");
		if(step != null) Element.addClassName(step.control, "on");
		this._activeStep = step;
		this._activeStepIx = stepIx;
		this.buildHeader();
	}
	
	this._btnPrev.setEnabled(stepIx != 0);
	this._btnNext.setText( (stepIx >= this._steps.length-1) ? "Finish" : "Next" );
	
	Element.removeClassName(this._container, "off");
	
	this.onChangeStep(stepIx);
	if(finished && this.validateWizard()) this.onFinish();
}

Wizard.prototype.validateWizard = function() {
	for(var i=0; i<this._steps.length; i++) {
		var step = this._steps[i];
		if(step.validation && !step.validation.validate()) {
			this.setActiveStep(i);
			return false;
		}
	}
	return true;
}

Wizard.prototype.clearContainerContents = function(container) {
	while(container.childNodes.length > 0) container.removeChild(container.childNodes[0]);
}

Wizard.prototype.anchor_onClick = function(e) {
	var a = Event.findElement(e, "a");
	this.setActiveStep(a.stepIx);
	return false;
}
Wizard.prototype.btnNext_onClick = function(e) {
	this.setActiveStep(this._activeStepIx+1);
}
Wizard.prototype.btnPrev_onClick = function(e) {
	this.setActiveStep(this._activeStepIx-1);
}

// LinkButton
function LinkButton(element) {
	this._element = element;
	Event.observe(this._element, "click", this.a_onClick.bindAsEventListener(this));
}
Object.extend( LinkButton.prototype, Event.Publisher );
LinkButton.prototype.setText = function(text) {
	var ctrl = this._element;
	var lastCtrl = this._element;
	while(ctrl.nodeName != "#text") {
		lastCtrl = ctrl;
		ctrl = ctrl.firstChild;
	}
	ctrl = lastCtrl;
	clearContents(ctrl);
	ctrl.appendChild(document.createTextNode(text));
}
LinkButton.prototype.setEnabled = function(enabled) {
	if(enabled && Element.hasClassName(this._element, "disabled")) Element.removeClassName(this._element, "disabled");
	if(!enabled && !Element.hasClassName(this._element, "disabled")) Element.addClassName(this._element, "disabled");
}
LinkButton.prototype.a_onClick = function(e) { this.dispatchEvent("click", e.event_data); }

// PushButton
function PushButton(element) {
	this._element = element;
	Event.observe(this._element, "click", this.input_onClick.bindAsEventListener(this));
}
Object.extend( PushButton.prototype, Event.Publisher );
PushButton.prototype.setText = function(text) {
	this._element.value = text;
}
PushButton.prototype.setEnabled = function(enabled) {
	if(enabled && Element.hasClassName(this._element, "disabled")) Element.removeClassName(this._element, "disabled");
	if(!enabled && !Element.hasClassName(this._element, "disabled")) Element.addClassName(this._element, "disabled");
}
PushButton.prototype.input_onClick = function(e) { this.dispatchEvent("click", e.event_data); }

// Object.clone
Object.prototype.clone = function(deep) {
  var objectClone = new this.constructor();
  for (var property in this)
    if (!deep)
      objectClone[property] = this[property];
    else if (typeof this[property] == 'object')
      objectClone[property] = this[property].clone(deep);
    else
      objectClone[property] = this[property];
  return objectClone;
}


